import { ChangeAction, ChangeRecord, CollectionMonitor } from "./CollectionMonitor"
import Monitor from "./Monitor"
import funcUtil from "../utils/func.util"
import ObservableMap from "../observer/observable.map"
import EngineContext from "../EngineContext"
export default class MapMonitor<A extends ObservableMap = ObservableMap> extends CollectionMonitor {
  target: A
  constructor(target: A, config: any, updatePhaseSync?: EngineContext) {
    super(config, updatePhaseSync)
    this.target = target
    for (const n of target.keys) {
      const r = target.get(n)
      const o = new Monitor(r, config, updatePhaseSync)
      o.onChanged(this.triggerChangeHandlers)
      this.targetMonitors[n] = o
    }
    const o = {
      onAdded: (e, o) => {
        const a = new Monitor(e, config, updatePhaseSync)
        a.onChanged(this.triggerChangeHandlers)
        this.targetMonitors[o] = a
        const l = this.diffRecord.findIndex(e => e.index === o)
        l > -1 && this.diffRecord.splice(l, 1)
        const c = new ChangeRecord(o, ChangeAction.added, funcUtil.deepCopy(e))
        l > -1 && this.diffRecord.push(c), this.triggerChangeHandlers(c)
      },
      onRemoved: (e, t) => {
        delete this.targetMonitors[t]
        const i = this.diffRecord.findIndex(e => e.index === t)
        i > -1 && this.diffRecord.splice(i, 1)
        const s = new ChangeRecord(t, ChangeAction.removed, funcUtil.deepCopy(e))
        i === -1 && this.diffRecord.push(s), this.triggerChangeHandlers(s)
      }
    }
    this.target.onElementChanged(o)
  }
  commitChanges() {
    this.invokeCallbacks(this.getDiffRecord())
  }
  getDiffRecord() {
    const e: ChangeRecord[] = []
    for (const t in this.targetMonitors) {
      const i = this.targetMonitors[t]
      if (i.hasDiffRecord()) {
        const s = i.getDiffRecord()
        const o = this.diffRecord.findIndex(e => e.index === t)
        if (o > -1) {
          funcUtil.merge(this.diffRecord[o].diff, s)
        } else {
          e.push(new ChangeRecord(t, ChangeAction.updated, s))
        }
      }
    }
    return this.diffRecord.concat(e)
  }
}
